Kotlin Android开发一些心得

一周前开始学习kotlin,现在已经在项目中开发使用了。我目前负责的项目老代码非常多,之前的java代码已经有十多万行了。所以即便使用了kotlin,也只是在新建文件的代码里使用,老代码继续用java。kotlin的好处就是完全兼容java,java调用kotlin,kotlin基本上无阻碍。

先说说为什么要转kotlin

  1. Google已经明确kotlin为第一官方语言。我相信Google的决意,就像当初毫不犹豫的抛弃eclipse转向as。kotlin已经是不可避免的大势所趋了。

  2. Kotlin与java代码完全兼容。使用kotlin就好像只是增加了一个库。打个比方,Rxjava比较难上手吧,不懂Rxjava的人看Rxjava像看天书,更不知从何写起。kotlin学起来比Rxjava简单的多。

  3. 作为一名程序猿,我是非常追求代码的简洁高效。在代码简洁上,kotlin简直是神器,太和我心意了。由于要兼容低版本,之前就一直在用java的lambda表达式插件,但是很多java8的特性还是用不了。kotlin全部能做到,而且更好。在易理解的基础上,能用1行代码搞定的事我绝不会写两行。用了kotlin,我自己写的很多基础函数都用不着了。真正的Enjoy Coding!

也说一下目前遇到的一些问题

  1. 由于集成了kotlin包,apk会增大约0.5M。这看你的项目是否能接受了,我觉得还行。

  2. 目前没发现什么大坑。在java-kotlin互相调用时要小心,koltin如果不注明,是强制不为空的。如果你的java代码有良好的习惯,出入参都注明了@Nullable @Nonnull,就没什么问题了

安装与配置

参考kotlin官网

我的android studio 没有升级3.0预览版,使用的还是2.3版本。

  1. 首先更新kotlin语言插件


    屏幕快照 2017-05-30 下午6.17.38.png
  2. 工程里添加如下插件配置
//必须
apply plugin: 'kotlin-android' 
//快捷的findviewfindid操作,建议加上
apply plugin: 'kotlin-android-extensions' 

然后是依赖路径

buildscript {
    //可能由于androidstudio版本原因,老提示我这里使用1.1.2-3版本,最新应该是1.1.2-4,根据提示来即可
    ext.kotlin_version = '1.1.2-3'
    repositories {
        jcenter()
        //阿里的maven仓国内镜像,如果gradle下载很慢,建议使用该仓库
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        mavenCentral()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
    }
}

最后是编译依赖的仓库,用着这个就行了。

compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

注意几点:

  1. 如果之前使用了依赖于注解的库如Dragger,databinding等,需要额外的配置,详情请参考官网
  2. Anko 是一个封装了很多android操作的库,比如ui操作、异步操作、数据库操作等等。不过我目前觉得还用不着,就没加。感兴趣的同学可以自己去添加。

ok, 可以进入kotlin世界了!


我主要是参考了这本书 《Kotlin for Android developers》 ,加上一些自己的理解。内容不多,看几遍就记得差不多了。刚学习kotlin时可以下载下来,使用时随时查阅。

Koltin的类

kotlin的变量申明 val 是不可变变量,相当于java里的finalvar是可变变量,一般情况尽量使用val 。如果使用var一般都需要判空
val i = 7 //自动类型推导
val str:String = "hello"//也可以显式的指明类型
var name: String? = null//可变变量一般要注意使用安全操作符? ,使用时都要加上? val length = name?.length
这里有个小坑,如果没加传入了空参数是,kotlin会强制判空抛异常。

只要是Java语言有交互的参数,除非是100%确定不为空,否则请务必都加上安全操作符?

类继承
class CustomView(context: Context?, attrs: AttributeSet?) : View(context, attrs) 构造函数
额外添加一个属性name
class CustomView(val name:String, context: Context?, attrs: AttributeSet?) : View(context, attrs)
添加其他构造函数
class CustomView(context: Context?, attrs:AttributeSet?) : TextView(context, attrs){ constructor(name: String, context: Context?, attrs:AttributeSet?):this(context, attrs) { text = name } }

另外,kotlin不需要new操作符了,创建类直接调用其构造方法,就像使用普通函数那样。
val view = CustomView(context, attrs)

Kotlin的方法

方法申明差不多,动手写一下很快就明白了。
默认参数特别好用! 终于可以不用写一大堆同名函数了
动态方法扩展相当于将一大堆Util换种写法

比如异步加载图片的封装,java这样写

  public static void setImageUriAsync(@NonNull ImageView iv, String uri, boolean round) {
    ...    
  }

  public static void setImageUriAsync(@NonNull ImageView iv, String uri) {
        setImageUriAsync(iv, uri, false);
 }

kotlin这样写:

fun ImageView.setImageUrlAsync(url: String?, isRound: Boolean = false) {
    ...
}

调用时就当做imageview的普通方法使用即可

iv.setImageUrlAsync(url)
iv.setImageUrlAsync(url, true)

注意一点

在java里,所有的方法都要在声明在类里,一般一个类也只能有一个pulic方法。kotlin的方法可以独立放在类外面,左右全局使用,比如前面提到ImageView扩展方法就要单独放在类外部。kotlin一个文件可以申明多个全局方法,声明多个public类。就是说,很多东西都能放在kotlin一个文件里。

Koltin的Null处理

使用安全操作符?可以省略很多无意义判空操作
不多说,直接上代码,一看就都明白了。
以前这样写

    if (adapter != null) {
        List<CmdNotice> list = adapter.getDatas();
                if (list != null) {
                    for (CmdNotice it :list) {
                        if (it.getId() == notice.getId()) {
                            it.setStatus(notice.getStatus());
                            adapter.notifyDataSetChanged();
                            break;
                        }
                    }
                }
        }

现在这样写

adapter?.datas?.firstOrNull({ it.id == notice.id })?.let {
                    it.status = notice.status
                    adapter?.notifyDataSetChanged()
                }

静态常量,静态函数,单例

如果一个类里都是静态常量和静态函数,直接在最外面写

object Const{
    val MSG_1 = 1
    fun getCurrentDate():Date{
        return Date()
    }
}

如果是在普通类里有静态变量,以及单例,这样写

class MyCache{
    companion object {
        val TYPE = 1 //常量
        val instance = MyCache() //单例
    }
}

这样调用
MyCache.TYPE
MyCache.instance

kotlin的inline(内联)函数

内联函数与一般的函数不同,在编译时会做替换,少了普通函数调用的压栈出栈,更高效。因为是替换,所以可以识别传入的泛型
比如
inline fun <reified T> getClassName():String{ return T::class.java.name }
直接这样调用
val name = getClassName<AppCompatActivity>()

可以传入代码块,比如一个异步线程操作的代码块

object MyExecutor{
    val instance: ExecutorService = Executors.newCachedThreadPool()
}
inline fun doSync(crossinline block: () -> Unit) {
    MyExecutor.instance.execute { block() }
}

//调用如下。 传入的block代码块可以直接放在函数后面的{}里。
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        doSync{
            //Code: Request network
        }
    }

Kotlin基础库里大量的便捷操作以及Anko库里很多操作都是使用inline函数完成的。常用的when, apply, let,以及对list数组封装的各种操作firstOrNullfilter等都是内联函数完成的。

Koltin函数需要传入的代码块可以直接放在函数名的大括号里,不需要再用小扩号包起来。这样的话,很多调用就非常简洁
比如Anko库里的async, uiThread ,异步操作的写法比Rxjava简单的多!

        async{
            //Do step1 cost time
            uiThread { toast("complete step1") }
            //Do step2 cost time
            uiThread {  toast("complete step2")}
        }

而且其写法很巧妙,只保存了外部Activity的弱引用,如果在异步执行过程中Activity销毁了uiThread则不会调用,防止内存泄漏。

FindViewById

由于有了插件kotlin-android-extensions.
Activity里可以这样写,不需要在额外申明TextView变量了。所以注意xml文件里id的命名使用驼峰写法

        setContentView(R.layout.main)
        tvTitle.setOnClickListener { toast("hello") }

Adapter里这样写, ViewHolder完全不需要了

   view.tvName.text = notice.name
   view.tvNumber.text = ""
   view.ivIcon.setImageUrlAsync(icon, true)

其他

  1. 注意在kotlin中== 相当于java中的equal函数,=== 相当于java中的==。不过一般情况加==就够了。kotlin中没有基本类型,所有的如Int,Long都是对象。

  2. kotlin中没有三元操作符。可以用if else,或者 ?:代替。
    java: String a = result?"true":"false"
    kotlin:val a = if (result) "true" else "false"
    ?:表示先判断前面是否为空,为空的话就返回后面的
    java: String b = (a==null)?a:"true"
    kotlin: val b=a?:"true"

因为都是基于JVM,Kotlin的所有操作java当然都能做到,但是kotlin更简洁容易理解!
先到这里,如有问题欢迎指正,大家共同进步!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容